#pragma once

#include "PLObject.h"

class PLVertex;

/**
  *	A PLEdge object represents an edge with a specific direction, which is defined by
  * two PLVertex objects, where one is the "From"-vertex, the other is the
  * "To"-vertex. A PLEdge object corresponds to exactly one PLBlob object and can
  * have one or no adjacent PLEdge object of another PLBlob object.
  */
class PLEdge : public PLObject
{
public:
	PLEdge( const PLuint &fromVertexIndex, const PLuint &fromTexcoordIndex,
		const PLuint &toVertexIndex, const PLuint &toTexcoordIndex,
		const PLuint &imageID );
	PLEdge( const PLEdge &edge );
	virtual ~PLEdge( void );

	PLVertex &From( void );
	const PLuint &FromVertexIndex( void ) const;
	const PLuint &FromTexcoordIndex( void ) const;
	PLVertex &To( void );
	const PLuint &ToVertexIndex( void ) const;
	const PLuint &ToTexcoordIndex( void ) const;

	static const PLuint &GetNumEdges( void );

	const PLEdge *GetAdjacentEdge( void );
	void SetAdjacentEdge( PLEdge *adjacentEdge );
	
	/**
	  *	PLEdgeVICompare objects are used as Compare-objects in stl containers,
	  * when PLEdge objects are stored (and not pointers).
	  * Only the vertex indices are compared. Therefore the vertex indices of
	  * both edges are sorted in ascending order. This guarantees that the direction
	  * of the edges does not matter.
	  */
	static class PLEdgeVICompare
	{
	public:
		bool operator()(const PLEdge &first, const PLEdge &second) const;
	};

	/**
	  *	PLEdgeVIPCompare objects do the same as PLEdgeVICompare objects, but
	  * expect const pointers instead of const references in the ()-operator
	  */
	static class PLEdgeVIPCompare
	{
	public:
		bool operator()(const PLEdge *first, const PLEdge *second) const;
	};

	/**
	  * PLEdgeVIAndTICompare objects are used as Compare-objects in stl containers,
	  * when PLEdge objects are stored (and not pointers).
	  * Only the vertex indices and texture IDs are compared. Therefore the vertex indices of
	  * both edges are sorted in ascending order. This guarantees that the direction
	  * of the edges does not matter.
	  */
	static class PLEdgeVIAndTICompare
	{
	public:
		bool operator()(const PLEdge &first, const PLEdge &second) const;
	};

	/**
	  *	PLEdgeVIAndTIPCompare objects do the same as PLEdgeVIAndTICompare objects, but
	  * expect const pointers instead of const references in the ()-operator
	  */
	static class PLEdgeVIAndTIPCompare
	{
	public:
		bool operator()(const PLEdge *first, const PLEdge *second) const;
	};

	/**
	  * PLEdgeVIAndTICompare objects are used as Compare-objects in stl containers,
	  * when PLEdge objects are stored (and not pointers).
	  * Only the From-vertex indices are compared.
	  */
	static class PLEdgeJustFromVICompare
	{
	public:
		bool operator()(const PLEdge &first, const PLEdge &second) const;
	};

	/**
	  *	PLEdgeJustFromVIPCompare objects do the same as PLEdgeJustFromVICompare objects, but
	  * expect const pointers instead of const references in the ()-operator
	  */
	static class PLEdgeJustFromVIPCompare
	{
	public:
		bool operator()(const PLEdge *first, const PLEdge *second) const;
	};

private:
	/** The beginning of the PLEdge */
	PLVertex *mFrom;
	/** The end of the PLEdge */
	PLVertex *mTo;
	/** The adjacent PLEdge, which is part of the outline edges of another PLBlob object */
	PLEdge *mAdjacentEdge;

	/** Current number of PLEdge instances */
	static PLuint numEdges;
};